package moxl.xpath.axes;

import moxl.dom.MoxlNode;
import moxl.xpath.parser.types.NodeTestMatcher;

public enum XPathAxis {

	ANCESTOR("ancestor"),
	ANCESTOR_OR_SELF("ancestor-or-self"),
	ATTRIBUTE("attribute"),
	CHILD("child"),
	DESCENDANT("descendant"),
	DESCENDANT_OR_SELF("descendant-or-self"),
	FOLLOWING("following"),
	FOLLOWING_SIBLING("following-sibling"),
	NAMESPACE("namespace"),
	PARENT("parent"),
	PRECEDING("preceding"),
	PRECEDING_SIBLING("preceding-sibling"),
	SELF("self");
	
	private final String name;
	private XPathAxisStrategy strategy;

	XPathAxis(String name) {
		this.name = name;
		
		if (name.equals("child"))
		{
			strategy = new ChildAxisStrategy(this);
		} 
		else if (name.equals("attribute"))
		{
			strategy = new AttributeAxisStrategy(this);
		} 
		else if (name.equals("descendant")) 
		{
			strategy = new DescendantAxisStrategy();
		}
	}
	
    public Iterable<MoxlNode> getNodes(MoxlNode contextNode, NodeTestMatcher nodeTestMatcher) throws InvalidAxisForNodeException
    {
    	if (strategy==null) 
    	{
    		throw new UnsupportedOperationException("Cannot get node list as no strategy is defined for this axis: "+this);
    	}
    	return strategy.getNodes(contextNode, nodeTestMatcher);
    }

	public String getName()
    {
	    return name;
    }

	public static XPathAxis selectAxisByName(String name)
    {
	    if (name.equals("child")) {
	    	return CHILD;
	    }
	    else if (name.equals("attribute")) 
	    {
	    	return ATTRIBUTE;
	    }
	    for (XPathAxis axis : values()) 
	    {
	    	if (axis.getName().equals(name)) 
	    	{
	    		return axis;
	    	}
	    }
	    throw new IllegalArgumentException("No such axis: "+name);
    }
}
